#include "app_device.h"
#include "app_buffer.h"
#include "app_message.h"
#include "log.h"
#include "fcntl.h"
#include "unistd.h"
#include "string.h"
#include "stdlib.h"
#include "app_mqtt.h"
#include "app_common.h"
#include "app_pool.h"

static app_device_t *dev;

app_device_t *app_device_init(void)
{
    /* 创建设备结构体 */
    dev = (app_device_t *)malloc(sizeof(app_device_t));
    if (dev == NULL) {
        log_error("malloc dev error");
        return NULL;
    }
    dev->dev_filename = DEVICE_FILE_NAME;
    dev->dev_fd = open(dev->dev_filename, O_RDWR | O_APPEND);
    if (dev->dev_fd == -1) {
        perror("open dev error");
        log_error("打开蓝牙设备失败");
    }
    dev->read_thread = -1;
    dev->post_read = NULL;
    dev->pre_write = NULL;
    dev->is_runing = 0;
    dev->up_buffer = app_buffer_init();
    dev->down_buffer = app_buffer_init();

    return dev;
}

/**
 * @brief : 上行2号步骤，提交给线程池
 * 1.从上行缓冲区读取数据
 * 2.数据转换 字节数组转换为JSON
 * 3.把JSON发送消息队列
 * @param    arg: 
 * @return void* 
 */
static void *app_device_ip_2_send(void *arg)
{
    char read_buffer[100];
    /* 从上行缓冲区读取数据 */
    int read_size = app_buffer_read(dev->up_buffer, read_buffer, 100);
     
    /* 数据转换 字节数组转换为JSON */
    char *json_data = app_common_bytes_to_hexstr(read_buffer, read_size);

    /* 把JSON发送消息队列 */
    app_mqtt_send(json_data, strlen(json_data));

    return NULL;
}

/**
 * @brief : 从蓝牙设备文件读取数据 上行1号步骤 独立线程
 * 1 读取蓝牙设备文件中的数据
 * 2 a数据准换  读后预处理
 * 3 写入上行缓冲区
 * 4 将上行缓冲区数据提交给线程池
 * @param    arg: 
 * @return void* 
 */
static void *app_device_up_1_read(void *arg)
{
    int read_size;
    char read_buffer[100];
    while (1)
    {
        read_size = read(dev->dev_fd, read_buffer, 100);
        if (read_size == -1)
        {
            perror("read dev error");
            log_error("读取设备失败");
        }
        if (read_size > 0)
        {
            log_info("读取到数据：%d", read_size);
            app_common_bytes_print(read_buffer, read_size);

            /* 数据转换 读后预处理 */
            if (dev->post_read != NULL)
            {
                read_size = dev->post_read(read_buffer, read_size);
            }
            /* 写入上行缓冲区 */
            if (read_size > 0)
            {
                int ret = app_buffer_write(dev->up_buffer, read_buffer, read_size);
                if (ret == -1)
                {
                    log_error("写入上行缓冲区失败");
                    continue;
                }
                /* 将上行缓冲区数据提交给线程池 */
                app_pool_submit_task(app_device_ip_2_send, NULL);
            }
        }
    }
    return NULL;
}

/**
 * @brief : 下行2号步骤，提交给线程池
 * 1.从下行缓冲区读取数据
 * 2.数据转换 字节数组转换为HEX
 * 3.把HEX写入蓝牙设备文件
 * @param    arg: 
 * @return void* 
 */
static void *app_device_down_2_write(void *arg)
{
    char buffer[100];
    /* 从下行缓冲区读取数据 */
    int read_size = app_buffer_read(dev->down_buffer, buffer, 100);

    /* 把字节数组  转换为蓝牙格式 */
    if (dev->pre_write != NULL)
    {
        read_size = dev->pre_write(buffer, read_size);
    }
    log_info("向蓝牙设备文件写入数据：");
    app_common_bytes_print(buffer, read_size);

    /* 写入蓝牙设备文件 */
    log_info("写入蓝牙设备文件：%d , fd : %d", read_size, dev->dev_fd);
    int write_size = write(dev->dev_fd, buffer, read_size);
    if (write_size != read_size)
    {
        perror("write dev error");
        log_error("写入设备失败");
    }
    
    return NULL;
}

/**
 * @brief : 下行1号步骤
 * 1 数据转换 JSON 转换字节数组
 * 2 写入下行缓冲区
 * 3 将下行缓冲区数据提交给线程池
 * @param    json: 
 * @param    len: 
 * @return int 
 */
static int app_device_down_1(char *json ,int len)
{
    log_info("接收到MQTT数据:%s", json);
    /* aa数据准混 JSON 转换字节数组 */
    char *bytes_buff[100];
    int bytes_len = app_message_json_to_bytes(json, bytes_buff,100);
    /* i写入下行数据缓冲区 */
    app_buffer_write(dev->down_buffer, bytes_buff, bytes_len);
    /* 将下行步骤2 提交给线程池 */
    app_pool_submit_task(app_device_down_2_write, NULL);

    return 0;
}

void app_device_start(void)
{
    /* 启动从b蓝牙设诶文件读取的线程 */
    pthread_create(&dev->read_thread, NULL, app_device_up_1_read, NULL);
    /* 向MQTT模块注册接收到数据的回调函数 */
    app_mqtt_register_recv_callback(app_device_down_1);
    /* 启动线程池 */
    dev->is_runing = 1;
}


void app_device_destroy(void)
{
    /* 销毁缓冲区 */
    app_buffer_destroy(dev->up_buffer);
    app_buffer_destroy(dev->down_buffer);

    /* 关闭文件 */
    close(dev->dev_fd);

    /* 销毁设备结构体 */
    free(dev);
}

